import { Op } from 'sequelize';
import type { FindOptions } from 'sequelize';
import { BaseRepository } from './BaseRepository.js';
import type { DatabaseConnectionType } from '../connection.js';
import {
  Component,
  ComponentProp,
  ComponentExample,
  ComponentImport,
} from '../models/index.js';
import type {
  ComponentAttributes,
  ComponentCreationAttributes,
} from '../models/index.js';

/**
 * Component 数据访问层
 */
export class ComponentRepository extends BaseRepository<
  Component,
  ComponentAttributes,
  ComponentCreationAttributes
> {
  constructor(connection: DatabaseConnectionType) {
    super(Component, connection);
  }

  /**
   * 根据名称查找组件
   */
  async findByName(name: string): Promise<Component | null> {
    return await this.findOne({
      where: { name },
      include: [
        { model: ComponentProp, as: 'props' },
        { model: ComponentExample, as: 'examples' },
        { model: ComponentImport, as: 'imports' },
      ],
    });
  }

  /**
   * 根据分类查找组件
   */
  async findByCategory(
    category: string,
    options?: {
      limit?: number;
      offset?: number;
      framework?: string;
    }
  ): Promise<{ rows: Component[]; count: number }> {
    const whereClause: any = { category };
    
    if (options?.framework) {
      whereClause.framework = options.framework;
    }

    return await this.findAndCountAll({
      where: whereClause,
      include: [
        { model: ComponentProp, as: 'props' },
        { model: ComponentExample, as: 'examples' },
        { model: ComponentImport, as: 'imports' },
      ],
      limit: options?.limit || 20,
      offset: options?.offset || 0,
      order: [['popularity_score', 'DESC']],
    });
  }

  /**
   * 搜索组件
   */
  async searchComponents(
    query: string,
    options?: {
      category?: string;
      framework?: string;
      limit?: number;
      offset?: number;
    }
  ): Promise<{ rows: Component[]; count: number }> {
    const whereClause: any = {
      [Op.or]: [
        { name: { [Op.like]: `%${query}%` } },
        { description: { [Op.like]: `%${query}%` } },
        { search_keywords: { [Op.like]: `%${query}%` } },
      ],
    };

    if (options?.category) {
      whereClause.category = options.category;
    }

    if (options?.framework) {
      whereClause.framework = options.framework;
    }

    return await this.findAndCountAll({
      where: whereClause,
      include: [
        { model: ComponentProp, as: 'props' },
        { model: ComponentExample, as: 'examples' },
        { model: ComponentImport, as: 'imports' },
      ],
      limit: options?.limit || 20,
      offset: options?.offset || 0,
      order: [['popularity_score', 'DESC']],
    });
  }

  /**
   * 获取热门组件
   */
  async getPopularComponents(
    limit: number = 10,
    framework?: string
  ): Promise<Component[]> {
    const whereClause: any = {};
    
    if (framework) {
      whereClause.framework = framework;
    }

    return await this.findAll({
      where: whereClause,
      include: [
        { model: ComponentProp, as: 'props' },
        { model: ComponentExample, as: 'examples' },
        { model: ComponentImport, as: 'imports' },
      ],
      order: [['popularity_score', 'DESC']],
      limit,
    });
  }

  /**
   * 更新组件受欢迎程度
   */
  async updatePopularityScore(componentId: number, increment: number = 1): Promise<void> {
    await this.model.increment('popularity_score', {
      by: increment,
      where: { id: componentId },
    });
  }

  /**
   * 获取所有分类
   */
  async getCategories(): Promise<string[]> {
    const result = await this.model.findAll({
      attributes: ['category'],
      group: ['category'],
    });

    return result.map((item: any) => item.category);
  }

  /**
   * 根据分类统计组件数量
   */
  async getComponentCountByCategory(): Promise<Array<{ category: string; count: number }>> {
    const result = await this.model.findAll({
      attributes: [
        'category',
        [this.connection.getSequelize().fn('COUNT', '*'), 'count'],
      ],
      group: ['category'],
      order: [[this.connection.getSequelize().literal('count'), 'DESC']],
    });

    return result.map((item: any) => ({
      category: item.category,
      count: parseInt(item.dataValues.count, 10),
    }));
  }

  /**
   * 批量创建组件及其相关数据
   */
  async createWithRelations(componentData: {
    component: ComponentCreationAttributes;
    props?: Array<Omit<ComponentProp['_attributes'], 'id' | 'component_id' | 'created_at'>>;
    examples?: Array<Omit<ComponentExample['_attributes'], 'id' | 'component_id' | 'created_at'>>;
    imports?: Array<Omit<ComponentImport['_attributes'], 'id' | 'component_id' | 'created_at'>>;
  }): Promise<Component> {
    return await this.transaction(async (transaction) => {
      // 创建主组件
      const component = await this.create(componentData.component, { transaction });

      // 创建属性
      if (componentData.props && componentData.props.length > 0) {
        const propsData = componentData.props.map(prop => ({
          ...prop,
          component_id: component.id,
        }));
        await ComponentProp.bulkCreate(propsData as any, { transaction });
      }

      // 创建示例
      if (componentData.examples && componentData.examples.length > 0) {
        const examplesData = componentData.examples.map(example => ({
          ...example,
          component_id: component.id,
        }));
        await ComponentExample.bulkCreate(examplesData as any, { transaction });
      }

      // 创建导入语句
      if (componentData.imports && componentData.imports.length > 0) {
        const importsData = componentData.imports.map(importStmt => ({
          ...importStmt,
          component_id: component.id,
        }));
        await ComponentImport.bulkCreate(importsData as any, { transaction });
      }

      // 重新查询完整数据
      return await this.findByPk(component.id, {
        include: [
          { model: ComponentProp, as: 'props' },
          { model: ComponentExample, as: 'examples' },
          { model: ComponentImport, as: 'imports' },
        ],
        transaction,
      }) as Component;
    });
  }

  /**
   * 删除组件及其相关数据
   */
  async deleteWithRelations(componentId: number): Promise<boolean> {
    return await this.transaction(async (transaction) => {
      // 由于设置了 CASCADE 删除，只需要删除主组件
      const result = await this.destroy({
        where: { id: componentId },
        transaction,
      });

      return result > 0;
    });
  }
}